/************************************************************************/
/*Copyright (c) James Zhao 2007,2008
/*This file is part of AdminOverlay.
/*AdminOverlay is free software: you can redistribute it and/or modify
/*it under the terms of the GNU General Public License as published by
/*the Free Software Foundation, either version 3 of the License, or
/*(at your option) any later version.
/*
/*AdminOverlay is distributed in the hope that it will be useful,
/*but WITHOUT ANY WARRANTY; without even the implied warranty of
/*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
/*GNU General Public License for more details.
/*
/*You should have received a copy of the GNU General Public License
/*along with Foobar.  If not, see <http://www.gnu.org/licenses/>.                                                                     */
/*************************************************************************/
#include "UIControl.h"
#include "UIManager.h"

UIControl::UIControl( int pX, int pY, int pWidth, int pHeight ) 
	:position(pX,pY), width(pWidth), height(pHeight), globalPos(pX, pY)
{
	onBoundsChanged();
	NeedUpdate(true);
	isVisible = true;
}
UIControl::~UIControl(void)
{
	
}

int UIControl::Height() const
{
	return height;
}
int UIControl::Width() const
{
	return width;
}
int UIControl::X() const
{
	return position.x();
}

int UIControl::Y() const
{
	return position.y();
}
bool UIControl::NeedUpdate() const
{
	return needUpdate;
}

void UIControl::X( int val )
{
	if(val != position.x())
	{	
		position.setX(val);
		onBoundsChanged();
		NeedUpdate(true);
	}
}


void UIControl::Y( int val )
{
	if(val != position.y())
	{
		position.setY(val);
		onBoundsChanged();
		NeedUpdate(true);
	}
}

void UIControl::Width( int val )
{
	if (val != width)
	{	
		width = val;
		onBoundsChanged();
		NeedUpdate(true);
	}
}


void UIControl::Height( int val )
{
	if(val != height)
	{	
		height = val; 
		onBoundsChanged();
		NeedUpdate(true);
	}
}

 bool UIControl::IsVisible() const
{	
	return isVisible;
}

void UIControl::IsVisible( bool val )
{
	
	isVisible = val;
}

void UIControl::onDeviceReset()
{
	for(int i = 0; i < children.size(); i++)
	{
		children.at(i)->onDeviceReset();
	}
	onBoundsChanged();
}

void UIControl::layout( QPoint offset )
{
	layoutSelf(offset);
	layoutChildren(offset);	
}
void UIControl::layoutSelf( QPoint offset )
{
	GlobalPos(position + offset);
}

void UIControl::layoutChildren( QPoint offset)
{
	int size=  children.size();
	for(int i = 0;i < size; i++)
	{
		children[i]->layout(globalPos);
	}
}

QRect UIControl::AbsoluteBounds() const
{
	return absoluteBounds;
}

void UIControl::AbsoluteBounds( QRect val )
{
	if(absoluteBounds != val)
	{
		absoluteBounds = val;
		NeedUpdate(true);
	}
}

void UIControl::onBoundsChanged()
{
	absoluteBounds.setTopLeft(globalPos);
	absoluteBounds.setWidth(width);
	absoluteBounds.setHeight(height);
}

void UIControl::addControl( UIControl *control)
{
	control->Parent(this);
	children.push_back(control);
}

void UIControl::removeControl( UIControl *control)
{
	control->Parent(NULL);
	children.removeAt(children.indexOf(control));
}
QPoint UIControl::localToGlobal(QPoint pt )
{
	return globalPos + pt;
}

QPoint UIControl::globalToLocal( QPoint pt )
{
	return pt - globalPos;
}

const UIControl * UIControl::Parent() const
{
	return parent;
}

void UIControl::Parent( UIControl * val )
{
	parent = val;
}
const QList<UIControl*>* UIControl::Children() const
{
	return &children;
}

void UIControl::processOnKeyDown( int keyCode)
{
	emit keyDown(keyCode);
	int size = children.size();
	for(int i = 0;i < size; i++)
	{
		UIControl *child = children[i];
		child->processOnKeyDown(keyCode);
	}
}

void UIControl::processOnKeyUp( int keyCode)
{

	emit keyUp(keyCode);

	int size = children.size();
	for(int i = 0;i < size; i++)
	{
		UIControl *child = children[i];
		child->processOnKeyUp(keyCode);
	}
}


void UIControl::processOnKeyPress( int keyCode, bool isCtrlDown )
{
	emit keyPressed(keyCode, isCtrlDown);

	int size = children.size();
	for(int i = 0;i < size; i++)
	{
		UIControl *child = children[i];
		child->processOnKeyPress(keyCode, isCtrlDown);
	}
}
void UIControl::processOnMouseMove( QPoint point, bool isMouseDown )
{	
	bool isChildProcessingEvent = false;
	int size = children.size();
	for(int i = 0;i < size; i++)
	{
		UIControl* control = children.at(i);
		if(control->LocalBounds().contains(point))
		{
			isChildProcessingEvent = true;
		}

		QPoint childCoordPoint = point - control->Position();	
		control->processOnMouseMove(childCoordPoint, isMouseDown);
	}
	bool containsPt = QRect(0,0,width,height).contains(point);
	emit mouseMoved(point, isMouseDown, (!isChildProcessingEvent) &&
		containsPt);
}

void UIControl::processOnMouseDown( QPoint point )
{
	bool isChildProcessingEvent = false;
	int size = children.size();
	for(int i = 0;i < size; i++)
	{
		UIControl* control = children[i];

		QPoint childCoordPoint = point -  control->Position();		
		control->processOnMouseDown(childCoordPoint);
		if(control->LocalBounds().contains(point))
		{
			isChildProcessingEvent = true;
		}			
	}
	bool containsPt = QRect(0,0,width,height).contains(point);
	emit mouseDown(point, !isChildProcessingEvent && containsPt);
}
void UIControl::processOnMouseUp(QPoint point)
{
	int size = children.size();
	for(int i = 0;i < size; i++)
	{
		UIControl* control = children.at(i);
		QPoint childCoordPoint = point - control->Position();	

		control->processOnMouseUp(childCoordPoint );
	}
	bool containsPt = QRect(0,0,width,height).contains(point);
	emit mouseUp(point,  containsPt);
}


void UIControl::draw( LPDIRECT3DDEVICE9 device )
{
	if(IsVisible())
	{
		int size = children.size();
		for(int i = 0;i < size; i++)
		{
			children[i]->draw(device);
		}
	}
}

QRect UIControl::LocalBounds()
{
	QRect r;
	r.setTopLeft(position);
	r.setWidth(width);
	r.setHeight(height);
	return r;
}

QPointer<QObject> UIControl::Tag() const
{
	return tag;
}

void UIControl::Tag( QPointer<QObject> val )
{
	tag = val;
}

bool UIControl::HasFocus() const
{
	return hasFocus;
}

void UIControl::HasFocus( bool val )
{
	if(hasFocus != val)
	{
		hasFocus = val;
	}
}

void UIControl::NeedUpdate( bool val )
{
	if(needUpdate != val)
	{
		needUpdate = val;
		int size = children.size();
		for(int i = 0;i < size; i++)
		{
			children.at(i)->NeedUpdate(val);
		}
	}
}

QPoint UIControl::GlobalPos() const
{
	return globalPos;
}

void UIControl::GlobalPos( QPoint val )
{
	if(val != globalPos)
	{	
		globalPos = val;
		onBoundsChanged();
		NeedUpdate(true);
	}
}

QPoint UIControl::Position() const
{
	return position;
}

void UIControl::Position( QPoint val )
{
	if(position != val)
	{
		position = val;
		onBoundsChanged();
		NeedUpdate(true);
	}
}

void UIControl::GlobalX( int x )
{
	if(x != globalPos.x())
	{
		globalPos.setX(x);
		onBoundsChanged();
		NeedUpdate(true);
	}
}

int UIControl::GlobalX()
{
	return globalPos.x();

}

void UIControl::GlobalY( int y )
{
	if(y != globalPos.y())
	{
		globalPos.setY(y);
		onBoundsChanged();
		NeedUpdate(true);
	}
}

int UIControl::GlobalY()
{
	return globalPos.y();
}